package com.kcht.itsed.mws.aleframework.biz;

import com.kcht.itsed.mws.aleframework.intf.*;
import com.kcht.itsed.mws.aleframework.specmanage.ECSpecScheduleThread;
import com.kcht.itsed.mws.aleframework.specmanage.ISpecScheduleThread;
import com.kcht.itsed.mws.alemodel.*;
import com.kcht.itsed.mws.commmodel.CRAP;
import com.shhic.itsed.mws.deviceintf.RawTagOperationResult;
import com.shhic.itsed.mws.deviceintf.ReaderCommand;
import com.kcht.itsed.mws.persist.dao.IPhysicalReaderDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.*;

@Component
@Slf4j
public class ActiveSpecContainer implements IActiveSpecContainer{

	private Map<String,ECSpec> ecSpecMap = new HashMap<>();
	private Map<String,CCSpec> ccSpecMap = new HashMap<>();
	
	//每个活动规则都打开一个线程，线程中负责调度该规则的边界条件
	
	@Autowired
	@Qualifier("aleThreadPool")
	private ThreadPoolTaskExecutor mtf;

	@Autowired
	@Qualifier("aleThreadPool")
	private ThreadPoolTaskExecutor mes;

	@Autowired ReaderCommandFactoryGenerator readerCommandFactoryGenerator;
	@Autowired ISubscriptionSender subscriptionSender;

	@Autowired ITagMemoryContainer tmContainer;
	@Autowired ILogicalReaderContainer lrContainer;
	
	@Autowired IPhysicalReaderDao prDao;
	
	private Map<String,ISpecScheduleThread> specScheduleThreadMap = new HashMap<>();
	
		
	@Override
	public void notifyAllActiveSpecRefresh() {
		for(String ecSpecName:ecSpecMap.keySet()) {
			//以下两行代码有点重复，鉴于不是频繁调用，暂不处理
			IReaderCommandFactory rcf = readerCommandFactoryGenerator.generateFullyReaderCommands(ecSpecMap.get(ecSpecName));
			Set<ReaderCommand> allReaderCommandsOfASpec = rcf.generateReaderCommands();
			registerActiveECSpecThread(ecSpecName, ecSpecMap.get(ecSpecName), allReaderCommandsOfASpec);
		}
	}

	private void registerActiveECSpecThread(String specName,ECSpec ecSpec, Set<ReaderCommand> allReaderCommandsOfASpec) {
		ISpecScheduleThread sst;
		if(!specScheduleThreadMap.containsKey(specName)) {
			Set<TMFixedFieldSpec> tms = new HashSet<>();
			ecSpec.getReportSpecs().getReportSpec().forEach(ecReportSpec->{
				if(ecReportSpec.getOutput().getExtension() != null && ecReportSpec.getOutput().getExtension().getFieldList() != null) {
					ecReportSpec.getOutput().getExtension().getFieldList().getField().forEach(field->{
						TMFixedFieldSpec fieldDef = tmContainer.getFixedFieldDefination(field.getFieldspec().getFieldname());
						if(fieldDef != null)tms.add(fieldDef);
					});
				}
			});
			
			Map<String, Set<CRAP>> lrCraps = new HashMap<>();
			ecSpec.getLogicalReaders().getLogicalReader().forEach(lrName-> {
				//处理LR规则中以prName定义的规则：全部转换成crap方式
				lrCraps.put(lrName, new HashSet<>());
				LRSpec lrSpec = lrContainer.getLRSpec(lrName);
				lrSpec.getProperties().getProperty().stream()
					.filter(p->p.getName().equals("crap"))
					.forEach(p->lrCraps.get(lrName).add(new CRAP(p.getValue())));

				lrSpec.getProperties().getProperty().stream()
					.filter(p->p.getName().equals("prName"))
					.forEach(p->{
						prDao.findByName(p.getValue()).ifPresent(pre->{
							pre.getPrSpec().getAntennaList().getAntenna().forEach(a->{
								a.getProtocol().forEach(protocol->{
									lrCraps.get(lrName).add(new CRAP(pre.getPrSpec().getReaderId(),a.getAntennaNo(),protocol));
								});
							});
						});
					});
			});
			

			sst = new ECSpecScheduleThread(specName,ecSpec,tms,lrCraps,subscriptionSender);
		    mes.execute(sst);
			specScheduleThreadMap.put(specName, sst);
		}else {
			sst = specScheduleThreadMap.get(specName);
		}
		sst.registerRelatedReaderCommands(allReaderCommandsOfASpec);
	}
	

	@Override
	public synchronized void addActiveEC(String ecSpecName, ECSpec ecSpec) {
		ecSpecMap.put(ecSpecName, ecSpec);
	}

	@Override
	public synchronized void addActiveCC(String ccSpecName, CCSpec ccSpec) {
		ccSpecMap.put(ccSpecName,ccSpec);
	}

	@Override
	public synchronized void removeEC(String ecSpecName) {
		ecSpecMap.remove(ecSpecName);
		ISpecScheduleThread specScheduleThread = specScheduleThreadMap.remove(ecSpecName);
		if(specScheduleThread != null)specScheduleThread.stopThread();
	}

	@Override
	public synchronized void removeCC(String ccSpecName) {
		ccSpecMap.remove(ccSpecName);
	}
	@Override
	public List<Document> getAllSpecs() {
		List<Document> dl = new LinkedList<>();
		ecSpecMap.values().forEach(dl::add);
		ccSpecMap.values().forEach(dl::add);
		return dl;
		
	}
	@Override
	public void dispatchReverseTags(RawTagOperationResult tagRes) {
		specScheduleThreadMap.values().forEach(s->s.notifyReverseTagResult(tagRes));
	}
}
